package com.delta.rafg.core.database;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.junit.Test;

import com.delta.rafg.core.config.ConfigSettings;
import com.delta.rafg.core.database.impl.util.GenerateSeedData;
import com.delta.rafg.core.database.impl.util.GenerateSeedData.SEED_DATA_OPT;
import com.delta.rafg.core.exception.RAFGException;
import com.delta.rafg.core.log.RAFGLogger;

public class FullSyncroTestWithLocalCopy {

    //this test will perform multiple steps to do a full regression test on the syncro logic.
    //1) extract and copy the reference data to a local XE store.
    //2) extract and copy the local XE store version of master to a local XE cached store with data mangling enabled.
    //3) create an instance of the cache controller to manage auto syncing of local XE simulated master with local XE cache copy.
    //4) Manipulate specific fields of specific tables to make sure they get synced.
    @Test
    public final void testFullSyncroTestWithLocalCopy() {
        try {
            long startTime = System.currentTimeMillis();

//stage 1 - Extract SI reference data to local Oracle XE database.

            RAFGLogger.info("Starting Stage 1 - Extract SI reference data to local Oracle XE database");

            // 1) extract reference data and put into local copy in XE database
            ConfigSettings stage1ConfigSettings = ConfigSettings.newInstance("/com/delta/rafg/core/database/FullSyncroTestWithLocalCopy.ConfigSettings-Stage1.properties");
            IDataHandler refDataHandler = DataHandlerFactory.getReferenceDataHandler();
            refDataHandler.initialize("cmstables", stage1ConfigSettings);

            File sysTempDir = new File(System.getProperty("java.io.tmpdir"));
            File seedPath = new File(sysTempDir, "rafg/refdataseed");
            String seedFileName = "rafg_ref_seed.sql";
            GenerateSeedData generateSeedData = new GenerateSeedData();
            generateSeedData.setTestMode(false);
            Map<SEED_DATA_OPT, Object> seedDataParams = new HashMap<SEED_DATA_OPT, Object>();
            seedDataParams.put(SEED_DATA_OPT.DEST_PATH,  seedPath.getCanonicalPath());
            seedDataParams.put(SEED_DATA_OPT.SEED_FILE, seedFileName);
            seedDataParams.put(SEED_DATA_OPT.DEST_USER, stage1ConfigSettings.getProperty("com.delta.rafg.core.database.cache.username"));
            seedDataParams.put(SEED_DATA_OPT.DEST_PASS, stage1ConfigSettings.getProperty("com.delta.rafg.core.database.cache.password"));
            seedDataParams.put(SEED_DATA_OPT.DEST_SERVICE, "XE");
            seedDataParams.put(SEED_DATA_OPT.DEST_SCHEMA_SUFFIX, "");  // no schema suffix since this is emulating the reference data.
            generateSeedData.extractSeedData(refDataHandler, seedDataParams);

            RAFGLogger.info("Stage 1 extraction processing time: " + ((System.currentTimeMillis() - startTime) / 1000) + "s");

            //destroy this SI reference data connection.
            refDataHandler.destroy();
            refDataHandler = null;

            startTime = System.currentTimeMillis();

            //Stage 1, Part 2 - Load a seed handler to import the seed data to the XE database.
            IDataHandler seedHandler = DataHandlerFactory.getNewSeedDataHandler();
            DataHandlerOptions seedOpts = new DataHandlerOptions();
            seedOpts.setConfigSettings(stage1ConfigSettings);
            Map<String, Object> seedOptsMap = seedOpts.getDataHandlerSpecificOptionsMap();
            seedOptsMap.put("SeedFile", new File(seedPath, seedFileName).getCanonicalPath());
            seedOptsMap.put("SeedPath", new File(seedPath.getCanonicalPath()).getCanonicalPath());
            seedHandler.initialize(seedOpts);

            RAFGLogger.info("Stage 1 Oracle XE simulated data insertion processing time: " + ((System.currentTimeMillis() - startTime) / 1000) + "s");
            seedHandler.destroy();
            seedHandler = null;

//stage 2

            RAFGLogger.info("Starting Stage 2 - Extract local Oracle XE simluated reference data with data mangling turned on for import into local Oracle XE cache tables.");

            //stage 2, extract the local XE for insertion into the cache with data mangling turned on.
            startTime = System.currentTimeMillis();

            ConfigSettings stage2ConfigSettings = ConfigSettings.newInstance("/com/delta/rafg/core/database/FullSyncroTestWithLocalCopy.ConfigSettings-Stage2.properties");
            refDataHandler = DataHandlerFactory.getReferenceDataHandler();
            refDataHandler.initialize("cmstables", stage2ConfigSettings);

            sysTempDir = new File(System.getProperty("java.io.tmpdir"));
            seedPath = new File(sysTempDir, "rafg/refaltereddataseed");
            seedFileName = "rafg_ref_altered_seed.sql";
            generateSeedData.setTestMode(true);  //this turns on data mangling
            seedDataParams = new HashMap<SEED_DATA_OPT, Object>();
            seedDataParams.put(SEED_DATA_OPT.DEST_PATH,  seedPath.getCanonicalPath());
            seedDataParams.put(SEED_DATA_OPT.SEED_FILE, seedFileName);
            seedDataParams.put(SEED_DATA_OPT.DEST_USER, stage2ConfigSettings.getProperty("com.delta.rafg.core.database.cache.username"));
            seedDataParams.put(SEED_DATA_OPT.DEST_PASS, stage2ConfigSettings.getProperty("com.delta.rafg.core.database.cache.password"));
            seedDataParams.put(SEED_DATA_OPT.DEST_SERVICE, "XE");
            seedDataParams.put(SEED_DATA_OPT.DEST_SCHEMA_SUFFIX, stage2ConfigSettings.getProperty("com.delta.rafg.core.database.cache.schemasuffix"));
            generateSeedData.extractSeedData(refDataHandler, seedDataParams);

            RAFGLogger.info("Stage 2 - Extraction processing time: " + ((System.currentTimeMillis() - startTime) / 1000) + "s");

            //destroy this SI reference data connection.
            refDataHandler.destroy();
            refDataHandler = null;

            startTime = System.currentTimeMillis();

            //Stage 2, Part 2 - Load a seed handler to import the seed data to the XE database.
            seedHandler = DataHandlerFactory.getNewSeedDataHandler();
            seedOpts = new DataHandlerOptions();
            seedOpts.setConfigSettings(stage2ConfigSettings);
            seedOptsMap = seedOpts.getDataHandlerSpecificOptionsMap();
            seedOptsMap.put("SeedFile", new File(seedPath, seedFileName).getCanonicalPath());
            seedOptsMap.put("SeedPath", new File(seedPath.getCanonicalPath()).getCanonicalPath());
            seedHandler.initialize(seedOpts);

            RAFGLogger.info("Stage 2 - Oracle XE cache data insertion processing time: " + ((System.currentTimeMillis() - startTime) / 1000) + "s");
            seedHandler.destroy();
            seedHandler = null;

//stage 3 - load cache controller.  It will start up automatically, just need to intantiate it.
            RAFGLogger.info("Starting Stage 3 - Instantiating CacheController.  This will start the CacheController thread\n"
                    + "which will keep the cache database in sync with the reference database (local XE copy in this case)");

            CacheController cacheController = new CacheController(stage2ConfigSettings);

//stage 4 - alter simulated reference data.
            RAFGLogger.info("Starting Stage 4 - Oracle XE cache data insertion processing time: " + ((System.currentTimeMillis() - startTime) / 1000) + "s");

            //sleep for 2 mins to allow everything to come up and sync up.
            for (int i = 0; i < 240; i++) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                }
            }

            //sleep for awhile longer.
            for (int i = 0; i < 2400000; i++) {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    //e.printStackTrace();
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (RAFGException e) {
            e.printStackTrace();
        }
    }
}
